// TextDatabaseTable.cs
//
// Copyright (c) 2009 Mike Strobel
//
// This source code is subject to the terms of the Microsoft Reciprocal License (Ms-RL).
// For details, see <http://www.opensource.org/licenses/ms-rl.html>.
//
// All other rights reserved.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Threading;
using System.Windows.Data;

using Supremacy.Collections;

using System.Linq;

using Supremacy.Types;

namespace Supremacy.Text
{
    //internal class TextDatabaseTable<TEntry> : ITextDatabaseTable<TEntry>, INotifyCollectionChanged, INotifyChanged where TEntry : ILocalizedTextDatabaseEntry
    //{
    //    private readonly ReaderWriterLockSlim _syncLock;
    //    private readonly KeyedCollectionBase<string, TEntry> _entries;
    //    private readonly KeyedCollectionBase<string, TEntry> _newEntries;
    //    private readonly KeyedCollectionBase<string, TEntry> _deletedEntries;
    //    private readonly CompositeCollection _compositeView;

    //    private volatile bool _isChanged;

    //    protected ReaderWriterLockSlim SyncLock
    //    {
    //        get { return _syncLock; }
    //    }

    //    public TextDatabaseTable()
    //    {
    //        _syncLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
    //        _entries = new KeyedCollectionBase<string, TEntry>(entry => entry.Key);
    //        _newEntries = new KeyedCollectionBase<string, TEntry>(entry => entry.Key);
    //        _deletedEntries = new KeyedCollectionBase<string, TEntry>(entry => entry.Key);
    //        _compositeView = new CompositeCollection { _entries, _newEntries };

    //        ((INotifyCollectionChanged)_compositeView).CollectionChanged += OnChildCollectionChanged;
    //    }

    //    private void OnChildCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    //    {
    //        _syncLock.EnterReadLock();
    //        try
    //        {
    //            if (_isChanged)
    //                return;
    //            _isChanged = true;

    //            var handler = this.CollectionChanged;
    //            if (handler != null)
    //                handler(this, e);
    //        }
    //        finally
    //        {
    //            _syncLock.ExitReadLock();
    //        }
    //    }

    //    #region Implementation of IEnumerable
    //    public IEnumerator<TEntry> GetEnumerator()
    //    {
    //        _syncLock.EnterReadLock();
    //        try
    //        {
    //            return _compositeView.OfType<TEntry>().GetEnumerator();
    //        }
    //        finally
    //        {
    //            _syncLock.ExitReadLock();
    //        }
    //    }

    //    IEnumerator IEnumerable.GetEnumerator()
    //    {
    //        return GetEnumerator();
    //    }
    //    #endregion

    //    #region Implementation of ICollection<TEntry>
    //    public void Add(TEntry item)
    //    {
    //        AddNewEntry(item);
    //    }

    //    public void Clear()
    //    {
    //        _syncLock.EnterWriteLock();
    //        try
    //        {
    //            while (_entries.Count != 0)
    //            {
    //                var entry = _entries[0];
    //                _deletedEntries.Add(entry);
    //                _entries.RemoveAt(0);
    //            }
    //            while (_newEntries.Count != 0)
    //            {
    //                var entry = _newEntries[0];
    //                _deletedEntries.Add(entry);
    //                _newEntries.RemoveAt(0);
    //            }
    //        }
    //        finally
    //        {
    //            _syncLock.ExitWriteLock();
    //        }
    //    }

    //    private bool RemoveEntry(TEntry entry)
    //    {
    //        _syncLock.EnterWriteLock();
    //        try
    //        {
    //            if (!_entries.Remove(entry) && !_newEntries.Remove(entry))
    //                return false;
    //            _deletedEntries.Add(entry);
    //            return true;
    //        }
    //        finally
    //        {
    //            _syncLock.ExitWriteLock();
    //        }
    //    }

    //    public bool Contains(TEntry entry)
    //    {
    //        if (ReferenceEquals(entry, null))
    //            return false;

    //        _syncLock.EnterReadLock();
    //        try
    //        {
    //            return _compositeView.Contains(entry);
    //        }
    //        finally
    //        {
    //            _syncLock.ExitReadLock();
    //        }
    //    }

    //    public void CopyTo(TEntry[] array, int arrayIndex)
    //    {
    //        _syncLock.EnterReadLock();
    //        try
    //        {
    //            _compositeView.CopyTo(array, arrayIndex);
    //        }
    //        finally
    //        {
    //            _syncLock.ExitReadLock();
    //        }
    //    }

    //    public bool Remove(TEntry entry)
    //    {
    //        return RemoveEntry(entry);
    //    }

    //    public int Count
    //    {
    //        get
    //        {
    //            _syncLock.EnterReadLock();
    //            try
    //            {
    //                return _compositeView.Count;
    //            }
    //            finally
    //            {
    //                _syncLock.ExitReadLock();
    //            }
    //        }
    //    }

    //    public bool IsReadOnly
    //    {
    //        get { return false; }
    //    }
    //    #endregion

    //    #region Implementation of INotifyPropertyChanged
    //    public event PropertyChangedEventHandler PropertyChanged;
    //    #endregion

    //    #region Implementation of IChangeTracking
    //    public void AcceptChanges()
    //    {
    //        _syncLock.EnterWriteLock();
    //        try
    //        {
    //            PurgeDeletedItems();
    //            AcceptNewEntries();
    //            foreach (var entry in _entries.Where(o => o.IsChanged))
    //            {
    //                entry.AcceptChanges();
    //            }
    //        }
    //        finally
    //        {
    //            _syncLock.ExitWriteLock();
    //        }
    //    }

    //    public bool IsChanged
    //    {
    //        get { return _isChanged; }
    //        protected set
    //        {
    //            _syncLock.EnterReadLock();
    //            try
    //            {
    //                if (_isChanged)
    //                    return;
    //                _isChanged = value;
    //                RaiseChanged();
    //            }
    //            finally
    //            {
    //                _syncLock.ExitReadLock();
    //            }
    //        }
    //    }

    //    protected void RaiseChanged()
    //    {
    //        var handler = this.Changed;
    //        if (handler != null)
    //            handler(this, EventArgs.Empty);
    //    }
    //    #endregion

    //    #region Implementation of ITextDatabaseTable<TEntry>
    //    public TEntry this[string key]
    //    {
    //        get
    //        {
    //            _syncLock.EnterReadLock();
    //            try
    //            {
    //                TEntry entry;
    //                if (TryGetEntry(key, out entry))
    //                    return entry;
    //                throw new KeyNotFoundException();
    //            }
    //            finally
    //            {
    //                _syncLock.ExitReadLock();
    //            }
    //        }
    //    }

    //    public bool TryGetEntry(string key, out TEntry entry)
    //    {
    //        if (key == null)
    //        {
    //            entry = default(TEntry);
    //            return false;
    //        }
    //        _syncLock.EnterReadLock();
    //        try
    //        {
    //            return _entries.TryGetValue(key, out entry) || _newEntries.TryGetValue(key, out entry);
    //        }
    //        finally
    //        {
    //            _syncLock.ExitReadLock();
    //        }
    //    }

    //    public bool Remove(string key)
    //    {
    //        if (key == null)
    //            return false;
    //        _syncLock.EnterUpgradeableReadLock();
    //        try
    //        {
    //            TEntry entry;
    //            if (!TryGetEntry(key, out entry))
    //                return false;
    //            _syncLock.EnterWriteLock();
    //            try
    //            {
    //                return RemoveEntry(entry);
    //            }
    //            finally
    //            {
    //                _syncLock.ExitWriteLock();
    //            }
    //        }
    //        finally
    //        {
    //            _syncLock.ExitUpgradeableReadLock();
    //        }
    //    }

    //    public bool Contains(string key)
    //    {
    //        if (key == null)
    //            return false;
    //        TEntry entry;
    //        return TryGetEntry(key, out entry);
    //    }
    //    #endregion

    //    private void AddNewEntry(TEntry entry)
    //    {
    //        if (ReferenceEquals(entry, null))
    //            throw new ArgumentNullException("entry");

    //        _syncLock.EnterUpgradeableReadLock();
    //        try
    //        {
    //            if (_entries.Contains(entry.Key) || _newEntries.Contains(entry.Key))
    //                throw new ArgumentException("An entry with that key already exists.");
    //            _syncLock.EnterWriteLock();
    //            try
    //            {
    //                _newEntries.Add(entry);
    //                entry.Changed += OnEntryChanged;
    //            }
    //            finally
    //            {
    //                _syncLock.ExitWriteLock();
    //            }
    //        }
    //        finally
    //        {
    //            _syncLock.ExitUpgradeableReadLock();
    //        }
    //    }

    //    private void AcceptNewEntries()
    //    {
    //        _syncLock.EnterUpgradeableReadLock();
    //        try
    //        {
    //            if (_newEntries.Count == 0)
    //                return;
    //            _syncLock.EnterWriteLock();
    //            try
    //            {
    //                while (_newEntries.Count != 0)
    //                {
    //                    var entry = _newEntries[0];
    //                    _newEntries.RemoveAt(0);
    //                    _entries.Add(entry);
    //                }
    //            }
    //            finally
    //            {
    //                _syncLock.ExitWriteLock();
    //            }
    //        }
    //        finally
    //        {
    //            _syncLock.ExitUpgradeableReadLock();
    //        }
    //    }

    //    private void PurgeDeletedItems()
    //    {
    //        _syncLock.EnterUpgradeableReadLock();
    //        try
    //        {
    //            if (_deletedEntries.Count == 0)
    //                return;
    //            _syncLock.EnterWriteLock();
    //            try
    //            {
    //                while (_deletedEntries.Count != 0)
    //                {
    //                    var entry = _deletedEntries[0];
    //                    entry.Changed -= OnEntryChanged;
    //                    _deletedEntries.RemoveAt(0);
    //                }

    //            }
    //            finally
    //            {
    //                _syncLock.ExitWriteLock();
    //            }
    //        }
    //        finally
    //        {
    //            _syncLock.ExitUpgradeableReadLock();
    //        }
    //    }

    //    private void OnEntryChanged(object sender, EventArgs e)
    //    {
    //        this.IsChanged = true;
    //    }

    //    #region Implementation of INotifyCollectionChanged
    //    public event NotifyCollectionChangedEventHandler CollectionChanged;

    //    protected void OnCollectionReset()
    //    {
    //        var handler = this.CollectionChanged;
    //        if (handler != null)
    //            handler(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
    //    }
    //    #endregion

    //    #region Implementation of INotifyChanged
    //    public event EventHandler Changed;
    //    #endregion
    //}
}